home *** CD-ROM | disk | FTP | other *** search
- '
- ' ***********************************
- ' *** "FINAL APPROACH CONTROLLER" ***
- ' *** AN AIR TRAFFIC CONTROL GAME ***
- ' *** & TITLE SONG "BEACON BEATS" ***
- ' *** BY KEVIN MASON ***
- ' *** * * * * * * * * * * * * * * ***
- ' *** WRITTEN IN GFA BASIC 3.0 ***
- ' *** Version 1.2 ***
- ' * COPYRIGHT 1989 ANTIC PUBLISHING *
- ' ***********************************
- '
- CLEAR
- GOSUB inits
- ON ERROR GOSUB err_handler
- '
- DO
- ON MENU 100
- IF SUB(TIMER,elapsed_time%)>200 !'EVERY 200 GOSUB PAINTSCREEN' DOESN'T WORK
- GOSUB paint_screens
- ENDIF
- LOOP
- '
- ' *** DRAW MAIN GRAPHICS EVERY 1 SECOND ***
- '
- PROCEDURE paint_screens
- elapsed_time%=TIMER
- line4$=TIME$
- HIDEM
- VOID XBIOS(5,L:logbase1_adr%,L:-1,-1)
- ~C:asmmove1_adr%(L:grid_adr%,L:logbase1_adr%)!AS FAST AS SPUT$
- IF begin_storm! OR storm! OR storm_over! !OH! OH! THUNDERSTORMS!!!
- ~C:asmput_adr%(L:logbase1_adr%,L:storm_adr%(sf1%),tsx%(1),tsy%(1),w%,h%,sm%)
- ~C:asmput_adr%(L:logbase1_adr%,L:storm_adr%(sf2%),tsx%(2),tsy%(2),w%,h%,sm%)
- ENDIF
- FOR i%=1 TO 12 !TRAFFIC LIST
- IF BTST(lr|(i%),0) !AIRCRAFT ACTIVE?
- line1$=trafname$(i%)
- line2$=arvdest$(i%)
- ~C:asmtxt_adr%(L:*line1$,282,trafnamey%(i%))
- ~C:asmtxt_adr%(L:*line2$,282,arvdesty%(i%))
- IF BTST(lr|(i%),1) !AIRCRAFT INFLIGHT?
- at%=C:which_bit%(ca|(i%)) !WHICH ALTITUDE BIT IS TURNED ON?
- ht%=C:which_bit%(ch|(i%)) !WHICH HEADING BIT IS TURNED ON?
- line3$=" "+STR$(at%)+vor$(i%)+heading$(ht%)
- ~C:asmtxt_adr%(L:*line1$,acx%(i%),SUB(acy%(i%),12)) !AIRCRAFT ID
- ~C:asmtxt_adr%(L:*line3$,acx%(i%),SUB(acy%(i%),6)) !ALTITUDE - HEADING
- ~C:asmtxt_adr%(L:*point$,acx%(i%),acy%(i%)) !POINTER
- ENDIF
- ENDIF
- NEXT i%
- ~C:asmmove2_adr%(L:overlay_adr%,L:logbase1_adr%) !FASTER THAN PUT, MODE 6
- DEFTEXT 1,0,0,4
- ~C:asmtxt_adr%(L:*line4$,6,9)
- VOID XBIOS(5,L:-1,L:logbase1_adr%,-1) !SO WE CAN SEE MOUSE and NEW DRAWN SCRN
- SWAP logbase1_adr%,logbase2_adr% !SWITCH TO LOG2 SCREEN FOR HIDDEN DRAWING
- SHOWM
- DEFTEXT 0,0,0,4
- '
- IF all_activated!=FALSE !ANY AIRCRAFT LEFT TO SELECT FROM?
- GOSUB add_traffic !TIME TO ADD ANOTHER AIRCRAFT
- ENDIF
- '
- no_more_planes!=TRUE
- FOR i%=1 TO 12
- IF BTST(lr|(i%),1) !AIRCRAFT IS ACTIVE INFLIGHT
- GOSUB do_speed_check(i%) !MOVEMENT ROUTINES
- GOSUB location(i%) !LOCATION DETECTION ROUTINES
- no_more_planes!=FALSE !AT LEAST ONE AIRCRAFT IS ACTIVE
- ENDIF
- NEXT i%
- '
- GOSUB near_miss !NEAR MISS, COLLISION ROUTINES
- '
- GOSUB boolean_tests !OTHER IRREGULAR ROTUINES
- '
- RETURN
- '
- ' ***********************
- ' *** MAIN LOOP CALLS ***
- ' ***********************
- '
- ' *** MULTIPLE BOOLEAN TESTS ***
- '
- PROCEDURE boolean_tests
- '
- IF VAL(MID$(TIME$,4,2))=begin_storm% !RANDOM STORM GENERATOR
- begin_storm!=TRUE
- begin_storm%=0
- ENDIF
- IF begin_storm!=TRUE !STORM BUILD UP SEQUENCE
- GOSUB storm_begin
- ENDIF
- IF storm!=TRUE !STORM ROLLS ACROSS THE PRAIRIE
- GOSUB storm
- ENDIF
- IF storm_over!=TRUE !STORM DYING DOWN SEQUENCE
- GOSUB storm_over
- ENDIF
- '
- IF alert!=TRUE
- GOSUB blink_alert !SOUND ALARM
- ENDIF
- '
- IF begin_storm!=TRUE OR storm!=TRUE OR storm_over!=TRUE
- GOSUB move_storm !THUNDERSTORMS ON THE PROWL
- ENDIF
- '
- IF start!=TRUE
- GOSUB start_game
- ENDIF
- '
- IF all_activated!=TRUE AND no_more_planes!=TRUE
- GOSUB all_done !ALL 36 AIRCRAFT ACTIVATED, BUT NONE LEFT FLYING, GAME OVER
- ENDIF
- '
- RETURN
- '
- ' *** START GAME ***
- '
- PROCEDURE start_game
- VOID XBIOS(6,L:colrscr2_adr%) !LOAD COLOR PALETTE #2
- counter%=game_speed%
- GOSUB add_traffic
- start!=FALSE
- RETURN
- '
- ' *** BLINKING ALERT LIGHTS ***
- '
- PROCEDURE blink_alert
- IF alert!
- VOID XBIOS(32,L:alert_snd_adr%) !START VBI SOUND
- VOID XBIOS(7,8,red%)
- PAUSE 2
- VOID XBIOS(7,8,mgray%)
- alert!=FALSE !STOP FLASHING
- ENDIF
- RETURN
- '
- ' *** ERROR HANDLER ***
- '
- PROCEDURE err_handler
- er%=ERR
- VOID FORM_ALERT(1,ERR$(er%))
- RESUME NEXT
- RETURN
- '
- ' ********* MANAGE NEW TRAFFIC ROUTINES *********
- '
- ' *** TIME TO ADD A NEW PLANE TO TRAFFIC LIST ***
- '
- PROCEDURE add_traffic
- INC counter%
- IF counter%>=game_speed%+RANDOM(game_speed_var%) !20% VARIABILITY
- counter%=0
- i%=0
- DO !CHECK ALL 12 TRAFFIC LIST SLOTS
- INC i%
- IF i%>12 !ERROR TRAP
- i%=12
- GOTO jump_loop
- ENDIF
- IF MID$(trafname$(i%),2,1)=" " !FIND FIRST VACANT SPOT ON TRAFFIC LIST
- jr%=RANDOM(total_ac%-ac_count%) !SELECT RANDOM# BETWEEN 0 AND AC# LEFT
- IF jr%<0 OR jr%>(total_ac%-ac_count%-1)
- i%=12 !ERROR TRAP
- GOTO jump_loop
- ENDIF
- trafname$(i%)=ac$(jr%) !GET AIRCRAFT IDENTIFICATION #
- DELETE ac$(jr%) !DELETE FROM AIRCRAFT LIST
- INC ac_count% !KEEP COUNT OF AIRCRAFT ADDED
- IF ac_count%>=36 !GAME NEARLY OVER, HANDLED 36 AIRCRAFT
- all_activated!=TRUE
- ENDIF
- '
- SELECT ASC(MID$(trafname$(i%),2,1)) !GET AIRCRAFT LETTER DESIGNATION
- CASE 70 !ITS "F"
- lr|(i%)=BSET(lr|(i%),2) !AIRCRAFT IS F-15, SET SPEED BIT
- CASE 84 !ITS "T"
- lr|(i%)=BSET(lr|(i%),3) !AIRCRAFT IS T-37, SET SPEED BIT
- CASE 65 !IT "A"
- lr|(i%)=BSET(lr|(i%),4) !AIRCRAFT IS UH-1H, SET SPEED BIT
- DEFAULT !ERROR TRAP
- lr|(i%)=BSET(lr|(i%),3)
- acspeed!=TRUE
- ENDSELECT
- GOSUB activate_ac(i%)
- '
- jr2%=RANDOM(37) !RANDOMLY GET NUMBER 0 to 36
- IF jr2%<0 OR jr2%>36 !ERROR TRAP
- jr2%=1
- ENDIF
- arvdest$(i%)=ad$(jr2%) !GET FROM ARRIVAL-DESTINATION LIST
- IF MID$(arvdest$(i%),1,2)="DN"
- GOSUB place_inflight(i%,1,4) !FROM DNV, GOING SE
- ELSE IF MID$(arvdest$(i%),1,2)="OK"
- GOSUB place_inflight(i%,2,2) !FROM OKC, GOING SW
- ELSE IF MID$(arvdest$(i%),1,2)="AD"
- GOSUB place_inflight(i%,3,1) !FROM ADA, GOING W
- ELSE IF MID$(arvdest$(i%),1,2)="DF"
- GOSUB place_inflight(i%,4,0) !FROM DFW, GOING NW
- ELSE IF MID$(arvdest$(i%),1,2)="LU"
- GOSUB place_inflight(i%,5,6) !FROM LUB, GOING NE
- ELSE IF MID$(arvdest$(i%),1,2)="AM"
- GOSUB place_inflight(i%,6,4) !FROM AMR, GOING SE
- ELSE IF MID$(arvdest$(i%),1,2)="FS"
- GOSUB ready_takeoff(i%)
- ELSE IF MID$(arvdest$(i%),1,2)="LA"
- GOSUB ready_takeoff(i%)
- ENDIF
- i%=12
- ENDIF
- jump_loop:
- LOOP UNTIL i%=12
- ENDIF
- RETURN
- '
- ' *** ACTIVATE AIRCRAFT ***
- '
- PROCEDURE activate_ac(acn%)
- mc|(acn%)=BSET(mc|(acn%),1) !SET MOVEMENT COUNTER TO MOVEMENT #1
- sp|(acn%)=BSET(sp|(acn%),1) !SET SPEED COUNTER TO RESET
- lr|(acn%)=BSET(lr|(acn%),0) !SET AIRCRAFT ACTIVE BIT
- RETURN
- '
- ' *** PLACE AIRCRAFT INFLIGHT ***
- '
- PROCEDURE place_inflight(acn%,entry%,dir%)
- lr|(acn%)=BSET(lr|(acn%),1) !SET INFLIGHT BIT 'ON'
- ch|(acn%)=0 !CLEAR BYTE
- ch|(acn%)=BSET(ch|(acn%),dir%) !SET CURRENT HEADING
- dh|(acn%)=0 !CLEAR BYTE
- dh|(acn%)=BSET(dh|(acn%),dir%) !SET DESIRED HEADING
- vor|(acn%)=0 !SET VOR HOLD OFF
- vor$(acn%)=" " !NO 'v' ON RADAR ICON
- acx%(acn%)=entryx%(entry%) !SET ENTRY X,Y POSITION
- acy%(acn%)=entryy%(entry%)
- RETURN
- '
- ' *** PLACE AIRCRAFT AT AIRFIELD AWAITING TAKEOFF COMMAND ***
- '
- PROCEDURE ready_takeoff(acn%)
- ca|(acn%)=0 !CLEAR BYTE
- ca|(acn%)=BSET(ca|(acn%),0) !SET ALTITUDE TO ZERO, AND
- da|(acn%)=0 !CLEAR BYTE
- da|(acn%)=BSET(da|(acn%),0) !AWAIT TAKEOFF COMMAND
- vor|(acn%)=0 !SET VOR HOLD OFF
- vor$(acn%)=" " !NO 'v' ON RADAR ICON
- RETURN
- '
- ' ******* MOVEMENT CALCULATIONS *******
- '
- ' *** DETERMINE SPEED ***
- '
- PROCEDURE do_speed_check(ac%)
- speed%=lr|(ac%) AND &X11100 !MASK OUT SPEED BITS
- speed%=C:which_bit%(speed%) !WHICH SPEED BIT IS SET?
- IF BTST(sp|(ac%),speed%) !CHECK SPEED
- GOSUB do_move_head_alt !TIME TO MOVE
- sp|(ac%)=BCLR(sp|(ac%),speed%) !CLEAR SPEED COUNTER
- sp|(ac%)=BSET(sp|(ac%),1) !RESET SPEED COUNTER TO BIT #1 (RESET)
- ELSE
- sp|(ac%)=SHL(sp|(ac%),1) !INC SPEED COUNTER, DO NOT MOVE YET
- ENDIF
- RETURN
- '
- ' *** CHECK MOVE NUMBER, ADJUST HEADING AND ALTITUDE
- '
- PROCEDURE do_move_head_alt
- IF BTST(mc|(ac%),5) !CHECK HEADING-ALTITUDE EVERY FIFTH MOVE
- GOSUB move_plane
- GOSUB heading_altitude !CALCULATE NEW HEADING/ALT FOR NEXT 5 MOVES
- mc|(ac%)=BCLR(mc|(ac%),5) !CLEAR MOVEMENT #5
- mc|(ac%)=BSET(mc|(ac%),1) !RESET TO MOVEMENT #1
- ELSE
- GOSUB move_plane
- mc|(ac%)=SHL|(mc|(ac%),1) !INC COUNTER TO NEXT MOVEMENT
- ENDIF
- RETURN
- '
- ' *** MOVE AIRCRAFT RADAR TARGET ***
- '
- PROCEDURE move_plane
- SELECT ch|(ac%) !CALC NEW X,Y COORDINATES AND LIMIT TO BOUNDARIES
- CASE 128
- SUB acy%(ac%),MUL(ABS(acy%(ac%)>nb%),2) !NORTH
- CASE 64
- SUB acy%(ac%),MUL(ABS(acy%(ac%)>nb%),2) !NORTHEAST
- ADD acx%(ac%),MUL(ABS(acx%(ac%)<eb%),2)
- CASE 32
- ADD acx%(ac%),MUL(ABS(acx%(ac%)<eb%),2) !EAST
- CASE 16
- ADD acy%(ac%),MUL(ABS(acy%(ac%)<sb%),2) !SOUTHEAST
- ADD acx%(ac%),MUL(ABS(acx%(ac%)<eb%),2)
- CASE 8
- ADD acy%(ac%),MUL(ABS(acy%(ac%)<sb%),2) !SOUTH
- CASE 4
- ADD acy%(ac%),MUL(ABS(acy%(ac%)<sb%),2) !SOUTHWEST
- SUB acx%(ac%),MUL(ABS(acx%(ac%)>wb%),2)
- CASE 2
- SUB acx%(ac%),MUL(ABS(acx%(ac%)>wb%),2) !WEST
- CASE 1
- SUB acx%(ac%),MUL(ABS(acy%(ac%)>nb%),2) !NORTHWEST
- SUB acy%(ac%),MUL(ABS(acx%(ac%)>wb%),2)
- ENDSELECT
- RETURN
- '
- ' *** CALCULATE NEW HEADING AND ALTITUDE ***
- '
- PROCEDURE heading_altitude
- '
- IF BTST(vor|(ac%),0) !IF VOR HOLD ACTIVATED
- IF BTST(vor|(ac%),3) !IS LEFT TURN VOR HOLD ACTIVATED?
- lr|(ac%)=BSET(lr|(ac%),7) !LEFT TURN BIT ON
- lr|(ac%)=BCLR(lr|(ac%),6) !RIGHT TURN BIT OFF
- dh|(ac%)=ROL|(dh|(ac%),1) !INC DESIRED HEADING BY 45 DEGREES LEFT
- ENDIF
- IF BTST(vor|(ac%),4) !IS RIGHT TURN VOR HOLD ACTIVATED?
- lr|(ac%)=BSET(lr|(ac%),6) !RIGHT TURN BIT ON
- lr|(ac%)=BCLR(lr|(ac%),7) !LEFT TURN BIT OFF
- dh|(ac%)=ROR|(dh|(ac%),1) !INC DESIRED HEADING BY 45 DEGREES RIGHT
- ENDIF
- ENDIF
- '
- IF ch|(ac%) AND dh|(ac%) !CURRENT HEADING = DESIRED HEADING
- ELSE IF BTST(lr|(ac%),7) !NEED NEW CURRENT HEADING
- ch|(ac%)=ROL|(ch|(ac%),1) !INC HEADING BY 45 DEGREES LEFT
- ELSE
- ch|(ac%)=ROR|(ch|(ac%),1) !INC HEADING BY 45 DEGREES RIGHT
- ENDIF
- '
- IF ca|(ac%) AND da|(ac%) !CURRENT ALTITUDE = DESIRED ALTITUDE
- ELSE IF ca|(ac%)<da|(ac%) !CURRENT ALTITUDE BELOW DESIRED ALTITUDE
- ca|(ac%)=SHL|(ca|(ac%),-(ca|(ac%)<128)) !INC ALT BY 1000', BUT NOT>7000'
- ELSE !CURRENT ALTITUDE ABOVE DESIRED ALTITUDE
- ca|(ac%)=SHR|(ca|(ac%),-(ca|(ac%)>0)) !DEC ALT BY 1000', BUT NOT<0
- ENDIF
- RETURN
- '
- ' *** STORM BUILD UP SEQUENCE ***
- '
- PROCEDURE storm_begin
- IF sf1%=9
- storm!=TRUE
- begin_storm!=FALSE
- sf1%=1
- sf2%=4
- ENDIF
- DEC sf1%
- DEC sf2%
- RETURN
- '
- ' *** STORM SEQUENCE ***
- '
- PROCEDURE storm
- IF sf1%=8
- sf1%=1 !RESET STORM FROM NUMBER TO 1 AFTER 8 FRAMES SEEN
- ENDIF
- IF sf2%=8
- sf2%=1 !RESET STORM FROM NUMBER TO 1 AFTER 8 FRAMES SEEN
- ENDIF
- INC sf1%
- INC sf2%
- RETURN
- '
- ' *** STORM DYING DOWN SEQUENCE ***
- '
- PROCEDURE storm_over
- IF sf1%=16 !STORM DYING DOWN SEQUENCE
- storm_over!=FALSE
- sf1%=15
- sf2%=15
- ENDIF
- INC sf1%
- INC sf2%
- RETURN
- '
- ' *** CALCULATE NEW THUNDERSTORM CLOUDS POSITIONS ***
- '
- PROCEDURE move_storm
- IF storm_counter%=12 !STORMS MOVE AT 60 KNOTS
- FOR i%=1 TO 2 !MOVE STORMS NORTHEASTERLY
- SUB tsy%(i%),MUL(ABS(tsy%(i%)>nb%),2)
- ADD tsx%(i%),MUL(ABS(tsx%(i%)<eb%),2)
- IF change_course%=7 !GIVE SOME SOUTHERLY DRIFT TO THE THUNDERSTORMS
- FOR j%=1 TO 2
- INC tsy%(j%)
- INC tsx%(j%)
- NEXT j%
- change_course%=1
- ENDIF
- INC change_course% !STORM DRIFT COUNTER
- NEXT i%
- ENDIF
- INC storm_counter% !STORM MOVEMENT COUNTER
- IF storm_counter%=13
- storm_counter%=1
- ENDIF
- IF tsx%(1)>124 AND tsx%(1)<128 !STORM OVER
- storm!=FALSE
- storm_over!=TRUE
- IF begin_storm%=0 !BEGIN STORM DISSIPATION SEQUENCE
- sf1%=9 !SET STORM ANIMATION FRAMES TO #9
- sf2%=9
- begin_storm%=-1
- ENDIF
- ENDIF
- RETURN
- '
- ' ******* CHECK LOCATION ROUTINES *******
- '
- ' *** CHECK AIRCRAFT LOCATION ***
- '
- PROCEDURE location(ac%)
- '
- ' * OUT OF BOUNDS CHECK
- IF (PTST(acx%(ac%),acy%(ac%))=8 OR PTST(acx%(ac%),acy%(ac%))=2) AND BTST(ca|(ac%),7)=FALSE
- ' !OUT OF BOUNDS and NOT AT 7,000'
- alert!=TRUE
- INC err_or%
- GOSUB reset_ac
- ENDIF
- IF BTST(ca|(ac%),7) !STILL AT 7,000' and OUT OF BOUNDS
- IF (acx%(ac%)<10 OR acx%(ac%)>230) OR (acy%(ac%)<10 OR acy%(ac%)>185)
- alert!=TRUE
- INC err_or%
- GOSUB reset_ac
- ENDIF
- ENDIF
- '
- ' * WANDERED INTO RESTRICTED AREA?
- IF acy%(ac%)>70 AND acy%(ac%)<86
- IF (acx%(ac%)>54 AND acx%(ac%)<110) OR (acx%(ac%)>120 AND acx%(ac%)<160)
- alert!=TRUE
- INC err_or%
- ENDIF
- ENDIF
- '
- ' * WANDERED INTO THUNDERSTORM?
- IF PTST(SUB(acx%(ac%),2),ADD(acy%(ac%),2))=11
- alert!=TRUE
- INC collisions%
- GOSUB reset_ac
- ENDIF
- '
- ' * EXITING OR ENTERING AT FIX?
- IF acx%(ac%)=85 AND acy%(ac%)=13 !PAST "DNV FIX?
- GOSUB deactivate_ac(6,0,"DN",4) !AT 6,000' and GOING NW and DNV FIX?
- ENDIF
- IF acx%(ac%)=145 AND acy%(ac%)=13 !PAST "OKC" FIX?
- GOSUB deactivate_ac(6,6,"OK",2) !AT 6,000' and GOING NE and OKC FIX?
- ENDIF
- IF acx%(ac%)=207 AND acy%(ac%)=93 !PAST "ADA" FIX?
- GOSUB deactivate_ac(6,5,"AD",1) !AT 6,000' and GOING E and ADA FIX?
- ENDIF
- IF acx%(ac%)=147 AND acy%(ac%)=185 !PAST "DFW" FIX?
- GOSUB deactivate_ac(6,4,"DF",0) !AT 6,000' and GOING SE and DFW FIX?
- ENDIF
- IF acx%(ac%)=83 AND acy%(ac%)=185 !PAST "LUB" FIX?
- GOSUB deactivate_ac(6,2,"LU",6) !AT 6,000' and GOING SW and LUB FIX?
- ENDIF
- IF acx%(ac%)=23 AND acy%(ac%)=61 !PAST "AMR" FIX?
- GOSUB deactivate_ac(6,0,"AM",4) !AT 6,000' and GOING NW and AMR FIX?
- ENDIF
- '
- ' * AT 0' AND OVER AN AIRFIELD?
- IF BTST(ca|(ac%),0) AND acx%(ac%)=115 !AT 0' FOR LANDING?
- SELECT acy%(ac%)
- CASE 73 !OVER FORT SILL?
- GOSUB over_airfield("FS")
- CASE 113 !OVER LAWTON MUNI?
- GOSUB over_airfield("LA")
- ENDSELECT
- ENDIF
- '
- ' * OVER VOR?
- IF acx%(ac%)=115 AND acy%(ac%)=43 !AT VOR1 FIX?
- IF BTST(vor|(ac%),1) !ORDERED TO HOLD AT VOR1?
- vor|(ac%)=BSET(vor|(ac%),0) !ACTIVATE HOLD BIT
- SELECT ch|(ac%)
- CASE 1 TO 8 !HEADING S,SW,W,or NW?
- vor|(ac%)=BSET(vor|(ac%),4) !TURN LEFT AT VOR
- CASE 16 TO 128 !HEADING N,NE,E, or SE?
- vor|(ac%)=BSET(vor|(ac%),3) !TURN RIGHT AT VOR
- ENDSELECT
- ENDIF
- ENDIF
- IF acx%(ac%)=115 AND acy%(ac%)=153 !AT VOR2 FIX?
- IF BTST(vor|(ac%),2) !ORDERED TO HOLD AT VOR2?
- vor|(ac%)=BSET(vor|(ac%),0) !ACTIVATE HOLD BIT
- SELECT ch|(ac%)
- CASE 1 TO 8 !HEADING S,SW,W,or NW?
- vor|(ac%)=BSET(vor|(ac%),3) !TURN LEFT AT VOR
- CASE 16 TO 128 !HEADING N,NE,E, or SE?
- vor|(ac%)=BSET(vor|(ac%),4) !TURN RIGHT AT VOR
- ENDSELECT
- ENDIF
- ENDIF
- RETURN
- '
- ' *** DEACTIVATE AIRCRAFT, MAKE ROOM FOR ANOTHER AIRCRAFT ON LIST ***
- '
- PROCEDURE deactivate_ac(alt%,dir%,fix$,arv%)
- IF BTST(ch|(ac%),arv%) !arv%=ARRIVAL DIRECTION
- GOTO new_arrival
- ENDIF
- IF BTST(ca|(ac%),alt%) AND BTST(ch|(ac%),dir%) AND MID$(arvdest$(ac%),4,2)=fix$
- ' !PLANE EXITING AT 6,000' and PROPER HEADING and AT CORRECT FIX?
- INC hand_off% !SUCCESSFUL HAND OFF
- GOSUB reset_ac
- ELSE
- alert!=TRUE
- INC err_or% !HANDOFF IN ERROR DUE TO WRONG ALT, DIR, or FIX
- GOSUB reset_ac
- ENDIF
- new_arrival:
- RETURN
- '
- ' *** PLANE OVER AIRPORT ***
- '
- PROCEDURE over_airfield(af$)
- IF MID$(arvdest$(ac%),1,2)=af$ !JUST TAKING OFF FROM AIRFIELD?
- GOTO pop_over_airfield
- ENDIF
- IF MID$(arvdest$(ac%),4,2)=af$ !DESTINATION CORRECT AIRFIELD?
- GOSUB landed !GOING LANDING DIRECTION?
- ELSE !DESTINATION REALLY OTHER AIRFIELD?
- da|(ac%)=0 !CLEAR BYTE
- da|(ac%)=BSET(da|(ac%),1) !TOUCH AND GO, CLIMB BACK TO 1,000'
- ENDIF
- pop_over_airfield:
- RETURN
- '
- ' *** PLANE LANDED ***
- '
- PROCEDURE landed
- IF BTST(ch|(ac%),land_dir%) !CORRECT HEADING FOR LANDING?
- INC landed% !SUCCESSFUL LANDING
- GOSUB reset_ac
- ELSE !LANDED WRONG DIRECTION, PLANE CRASHED
- alert!=TRUE
- INC err_or%
- GOSUB reset_ac
- ENDIF
- RETURN
- '
- ' *** RESET AIRCRAFT ***
- '
- PROCEDURE reset_ac
- mc|(ac%)=0 !CLEAR MOVEMENT COUNTER BYTE
- sp|(ac%)=0 !CLEAR SPEED COUNTER
- vor|(ac%)=0 !CLEAR VOR BYTE
- vor$(ac%)=" " !NO 'v' ON RADAR ICON
- lr|(ac%)=bit7| !CLEAR LR BYTE, SET LEFT ON
- ca|(ac%)=bit7| !SET ALTITUDE 7,000'
- da|(ac%)=bit7|
- ch|(ac%)=bit7| !SET HEADING NORTH
- dh|(ac%)=bit7|
- trafname$(ac%)=" " !CLEAR TRAFFIC LIST
- arvdest$(ac%)=" "
- acx%(ac%)=280 !PARK PLANE
- acy%(ac%)=190
- RETURN
- '
- ' *** NEAR MISS AND COLLISION DETECTION
- '
- PROCEDURE near_miss
- j%=1
- FOR i%=1 TO 12
- IF BTST(lr|(i%),1) !AIRCRAFT IS ACTIVE INFLIGHT
- x%(j%)=acx%(i%) !BUILD TEMP ARRAY OF X,Y COORD AND ALTITUDES
- y%(j%)=acy%(i%) !OF ONLY INFLIGHT AIRCRAFT
- a|(j%)=ca|(i%)
- id|(j%)=i% !***TEMP ARRAY OF INFLIGHT AIRCRAFT ID#
- INC j%
- ENDIF
- NEXT i%
- FOR i%=1 TO SUB(j%,1) !CHECK ALL COMBINATIONS OF DISTANCES
- k%=ADD(i%,1) !BETWEEN INFLIGHT AIRCRAFT
- DO UNTIL k%=ADD(j%,1)
- VOID @nearmiss(x%(i%),x%(k%),y%(i%),y%(k%),a|(i%),a|(k%))
- INC k%
- LOOP
- NEXT i%
- ARRAYFILL x%(),0 !CLEAR TEMPORARY ARRAYS FOR NEXT NEARMISS CHECK
- ARRAYFILL y%(),0
- ARRAYFILL a|(),0
- ARRAYFILL id|(),0
- RETURN
- '
- ' *** CHECK AIRCRAFT SEPARATION - SAME ALTITUDE? LESS THAN 3 MILES? ***
- '
- FUNCTION nearmiss(x1%,x2%,y1%,y2%,alt1|,alt2|)
- IF alt1|=alt2| !AIRCRAFT AT SAME ALTITUDE?
- IF ADD(MUL(SUB(x1%,x2%),SUB(x1%,x2%)),MUL(SUB(y1%,y2%),SUB(y1%,y2%)))<899
- ' !CHECK HYPOTENUSE OF TRIAGLE BETWEEN AIRCRAFT 1 and AIRCRAFT 2 COORD
- alert!=TRUE
- INC conflict%
- VOID @collision(x1%,x2%,y1%,y2%)
- ENDIF
- ENDIF
- RETURN alert!
- ENDFUNC
- '
- ' *** CHECK AIRCRAFT SEPARATION - COLLISION? ***
- '
- FUNCTION collision(x1%,x2%,y1%,y2%)
- IF x1%=x2% AND y1%=y2%
- collision!=TRUE
- ac%=id|(i%)
- GOSUB reset_ac !REMOVE FIRST CRASHED PLANE FROM SCREEN
- ac%=id|(k%)
- GOSUB reset_ac !REMOVE SECOND CRASHED PLANE FROM SCREEN
- INC collisions%
- ENDIF
- RETURN collision!
- ENDFUNC
- '
- ' ******* HANDLE CLICKS ********
- '
- ' *** MOUSE BUTTON CLICK HANDLER ***
- '
- PROCEDURE click_handler
- SELECT MENU(10) !MOUSEX
- CASE 4 TO 40
- GOSUB pause_exit
- CASE 278 TO 315
- GOSUB select_aircraft
- CASE 199 TO 270
- GOSUB get_commands
- ENDSELECT
- RETURN
- '
- ' *** PAUSE OR EXIT GAME ***
- '
- PROCEDURE pause_exit
- SELECT MENU(11) !WHERE IS MOUSE Y COORDINATE
- CASE 14 TO 24 !PAUSE BUTTON CLICKED
- PUT 3,14,pause_off$,3
- m$=" Select PAUSE event | | Review Score Card or | Study Radar Screen "
- ALERT 2,m$,2,"SCORE|RADAR",b%
- IF b%=1
- GOSUB score_card
- ELSE
- DO
- LOOP UNTIL MOUSEK=1 !WAIT FOR LEFT MOUSE CLICK TO EXIT STUDY RADAR SCREEN
- elapsed_time%=TIMER
- ENDIF
- CASE 188 TO 199 !EXIT BUTTON CLICKED
- GOSUB all_done
- ENDSELECT
- RETURN
- '
- ' *** EXIT GAME ***
- '
- PROCEDURE all_done
- PUT 4,188,exit_off$,3
- PAUSE 10
- GOSUB restor_palette
- RETURN
- '
- ' *** SELECT AIRCRAFT ***
- '
- PROCEDURE select_aircraft
- IF MENU(11)>16 AND MENU(11)<195 !CLICKED WHICH OF 12 AIRCRAFT?
- oldsac%=sac%
- sac%=ADD(SUB(MENU(11),16) DIV 15,1) !AIRCRAFT# FOR COMMANDS UNTIL CHANGED
- IF ASC(MID$(trafname$(sac%),2,1))>33 !SOME TYPE OF AIRCRAFT IS ON LIST
- MID$(trafname$(oldsac%),1,1)=" " !ERASE * AT PREVIOUS AIRCRAFT
- MID$(trafname$(sac%),1,1)="*" !MOVE * TO SELECTED AIRCRAFT
- ELSE !ERROR TRAP, LIST EMPTY
- sac%=oldsac% !RESET PREVIOUSLY SELECTED AIRCRAFT
- CLR oldsac%
- ENDIF
- ENDIF
- RETURN
- '
- ' *** GET COMMANDS ***
- '
- PROCEDURE get_commands
- IF MID$(trafname$(sac%),1,1)="*" !IS TRAFFIC SELECTED FIRST?
- SELECT MENU(11)
- CASE 16 TO 26
- GOSUB clearance
- CASE 50 TO 75
- GOSUB vor
- CASE 98 TO 107
- GOSUB alt_1_3
- CASE 108 TO 117
- GOSUB alt_4_6
- CASE 140 TO 154
- GOSUB left_right
- CASE 159 TO 194
- GOSUB compass_rose
- ENDSELECT
- ENDIF
- RETURN
- '
- ' *** TAKEOFF/LAND ***
- '
- PROCEDURE clearance
- SELECT MENU(10)
- CASE 200 TO 238 !TAKEOFF COMMAND
- IF BTST(lr|(sac%),1)=0 !PLANE NOT INFLIGHT?
- PUT 200,16,takeoff_off$,3 !BUTTON PRESS EFFECT
- lr|(sac%)=BSET(lr|(sac%),1) !SET INFLIGHT BIT 'ON'
- ch|(sac%)=0 !CLEAR CURRENT HEADING BYTE
- ch|(sac%)=BSET(ch|(sac%),takeoff_dir%) !SET HEADING TAKEOFF DIRECTION
- dh|(sac%)=0 !CLEAR DESIRED HEADING BYTE
- dh|(sac%)=BSET(dh|(sac%),takeoff_dir%)
- ca|(sac%)=0 !CLEAR CURRENT ALTITUDE BYTE
- ca|(sac%)=BSET(ca|(sac%),0) !SET ALTITUDE 0'
- da|(sac%)=0 !CLEAR DESIRED ALTITUDE BYTE
- da|(sac%)=BSET(da|(sac%),1) !SET DESIRED INITIAL ALTITUDE 1,000'
- IF MID$(arvdest$(sac%),1,2)="FS"
- acx%(sac%)=entryx%(7) !SET TAKEOFF X,Y POSITION
- acy%(sac%)=entryy%(7)
- ELSE IF MID$(arvdest$(sac%),1,2)="LA"
- acx%(sac%)=entryx%(8) !SET TAKEOFF X,Y POSITION
- acy%(sac%)=entryy%(8)
- ENDIF
- ENDIF
- CASE 243 TO 267 !LAND COMMAND
- IF BTST(lr|(sac%),1) !IS AIRCRAFT FLYING?
- PUT 243,16,land_off$,3 !BUTTON PRESS EFFECT
- da|(sac%)=0 !CLEAR DESIRED ALTITUDE BYTE
- da|(sac%)=BSET(da|(sac%),0) !SET DESIRED ALTITUDE TO 0'
- ENDIF
- ENDSELECT
- RETURN
- '
- ' *** VOR1/VOR2 CLICKED ***
- '
- PROCEDURE vor
- IF MENU(10)>238 AND MENU(10)<266
- IF MENU(11)<62
- PUT 238,51,vor1_off$,3 !VOR 1 CLICKED
- PAUSE 8 !VOR BUTTON TOO SENSITIVE
- GOSUB vor_hold(1)
- ELSE
- PUT 238,64,vor2_off$,3 !VOR 2 CLICKED
- PAUSE 8 !VOR BUTTON TOO SENSITIVE
- GOSUB vor_hold(2)
- ENDIF
- ENDIF
- RETURN
- '
- ' *** VOR HOLD TOGGLE ***
- '
- PROCEDURE vor_hold(vor%)
- IF BTST(vor|(sac%),vor%) !TOGGLE VOR1 or VOR2 HOLD BIT
- vor|(sac%)=0 !VOR HOLD OFF
- vor$(sac%)=" " !REMOVE VOR MARKER FROM RADAR SCREEN
- ELSE
- vor|(sac%)=BSET(vor|(sac%),vor%) !VOR HOLD ON, AWAIT ARRIVAL VOR1 or VOR2
- vor$(sac%)="v" !MARK AIRCRAFT WITH VOR MARKER
- vor|(sac%)=BCLR(vor|(sac%),0) !VOR NOT ACTIVE UNTIL AIRCRAFT GETS THERE
- ENDIF
- RETURN
- '
- ' *** ALTITUDE 1,000 - 3,000 ***
- '
- PROCEDURE alt_1_3
- SELECT MENU(10)
- CASE 235 TO 246 !ALTITUDE 1,000 COMMAND
- da|(sac%)=0
- da|(sac%)=BSET(da|(sac%),1)
- PUT 236,98,alt1_off$,3
- CASE 247 TO 258 !ALTITUDE 2,000 COMMAND
- da|(sac%)=0
- da|(sac%)=BSET(da|(sac%),2)
- PUT 247,98,alt2_off$,3
- CASE 259 TO 270 !ALTITUDE 3,000 COMMAND
- da|(sac%)=0
- da|(sac%)=BSET(da|(sac%),3)
- PUT 259,98,alt3_off$,3
- ENDSELECT
- RETURN
- '
- ' *** ALTITUDE 4,000 - 7,000 ***
- '
- PROCEDURE alt_4_6
- SELECT MENU(10)
- CASE 235 TO 246 !ALTITUDE 4,000 COMMAND
- da|(sac%)=0
- da|(sac%)=BSET(da|(sac%),4)
- PUT 236,108,alt4_off$,3
- CASE 247 TO 258 !ALTITUDE 5,000 COMMAND
- da|(sac%)=0
- da|(sac%)=BSET(da|(sac%),5)
- PUT 247,108,alt5_off$,3
- CASE 259 TO 270 !ALTITUDE 6,000 COMMAND
- da|(sac%)=0
- da|(sac%)=BSET(da|(sac%),6)
- PUT 259,108,alt6_off$,3
- ENDSELECT
- RETURN
- '
- ' *** LEFT/RIGHT ***
- '
- PROCEDURE left_right
- SELECT MENU(10)
- CASE 233 TO 250 !LEFT TURN COMMAND
- PUT 233,140,left_off$,3
- lr|(sac%)=BSET(lr|(sac%),7) !LEFT TURN BIT ON
- lr|(sac%)=BCLR(lr|(sac%),6) !RIGHT TURN BIT OFF
- CASE 251 TO 268 !RIGHT TURN COMMAND
- PUT 252,140,right_off$,3
- lr|(sac%)=BSET(lr|(sac%),6) !RIGHT TURN BIT ON
- lr|(sac%)=BCLR(lr|(sac%),7) !LEFT TURN BIT OFF
- ENDSELECT
- RETURN
- '
- ' *** COMPASS ROSE ***
- '
- PROCEDURE compass_rose
- SELECT MENU(11)
- CASE 159 TO 164
- dh|(sac%)=0
- dh|(sac%)=BSET(dh|(sac%),7) !NORTH HEADING COMMAND
- PUT 222,158,head360_off$,3
- CASE 165 TO 171
- SELECT MENU(10)
- CASE 208 TO 226
- dh|(sac%)=0
- dh|(sac%)=BSET(dh|(sac%),0) !NORTHWEST HEADING COMMAND
- PUT 206,165,head315_off$,3
- CASE 240 TO 260
- dh|(sac%)=0
- dh|(sac%)=BSET(dh|(sac%),6) !NORTHEAST HEADING COMMAND
- PUT 238,165,head045_off$,3
- ENDSELECT
- CASE 172 TO 180
- SELECT MENU(10)
- CASE 199 TO 218
- dh|(sac%)=0
- dh|(sac%)=BSET(dh|(sac%),1) !WEST HEADING COMMAND
- PUT 198,173,head270_off$,3
- CASE 248 TO 266
- dh|(sac%)=0
- dh|(sac%)=BSET(dh|(sac%),5) !EAST HEADING COMMAND
- PUT 246,173,head090_off$,3
- ENDSELECT
- CASE 181 TO 187
- SELECT MENU(10)
- CASE 208 TO 226
- dh|(sac%)=0
- dh|(sac%)=BSET(dh|(sac%),2) !SOUTHWEST HEADING COMMAND
- PUT 206,181,head225_off$,3
- CASE 240 TO 260
- dh|(sac%)=0
- dh|(sac%)=BSET(dh|(sac%),4) !SOUTHEAST HEADING COMMAND
- PUT 238,181,head135_off$,3
- ENDSELECT
- CASE 188 TO 194
- dh|(sac%)=0
- dh|(sac%)=BSET(dh|(sac%),3) !SOUTH HEADING COMMAND
- PUT 222,188,head180_off$,3
- ENDSELECT
- RETURN
- '
- ' ************************************************
- ' *** INITIALIZATION ROUTINES AND TITLE SCREEN ***
- ' ************************************************
- '
- ' *** DIM, FILL ARRAYS, SETUP SCREENS, ASSEMBLER SOURCE CODES ***
- '
- PROCEDURE inits
- GOSUB get_rez_dir
- DIM sav_pal%(15),blank_pal%(15),fade%(8),fadec%(8)
- DIM lr|(12),sp|(12),mc|(12),ch|(12),dh|(12),ca|(12),da|(12),vor|(12)
- DIM acx%(12),acy%(12),heading$(8)
- DIM ac$(36),ad$(36),trafname$(12),arvdest$(12),vor$(12)
- DIM trafnamey%(12),arvdesty%(12)
- DIM entryx%(8),entryy%(8)
- DIM x%(12),y%(12),a|(12),id|(12)
- DIM storm_adr%(16),tsx%(2),tsy%(2)
- HIDEM
- DEFMOUSE 3
- GOSUB sav_palette
- GOSUB blank_screen
- ON MENU BUTTON 1,1,1 GOSUB click_handler
- physbase%=XBIOS(2)
- logbase%=XBIOS(3)
- RESERVE -256000 !GIVE ME SOME ROOM
- mem1%=MALLOC(32512) !ALLOCATE MEMORY FOR SCREENS
- mem2%=MALLOC(32512)
- mem3%=MALLOC(32512)
- mem4%=MALLOC(32512)
- mem5%=MALLOC(32512)
- mem6%=MALLOC(256) !ALLOCATE MEMORY FOR ASSEMBLER ROUTINES
- mem7%=MALLOC(256)
- mem8%=MALLOC(512)
- mem9%=MALLOC(256)
- mem10%=MALLOC(256)
- mem11%=MALLOC(19200) !animation frames
- titlescr_adr%=mem1%+256 AND &HFFFF00 !adjust screens to 256K boundary
- logbase1_adr%=mem2%+256 AND &HFFFF00
- logbase2_adr%=mem3%+256 AND &HFFFF00
- grid_adr%=mem4%+256 AND &HFFFF00 !grid picture
- overlay_adr%=mem5%+256 AND &HFFFF00 !overlay picture
- asmmove1_adr%=mem6% !assembler subroutines
- asmmove2_adr%=mem7%
- asmput_adr%=mem8%
- asmtxt_adr%=mem9%
- which_bit%=mem10%
- storm_scr_adr%=mem11% !STORM animation frames
- title_song$=SPACE$(1500)
- title_song_adr%=V:title_song$
- '
- EVERY 300 GOSUB red_off
- GOSUB play_title_song
- GOSUB title_screen
- GOSUB other_inits
- GOSUB load_grid_screen
- GOSUB load_overlay_screen
- GOSUB load_make_puts
- GOSUB setup_asm
- GOSUB fade_in
- '
- ' *** BYTE DEFINITIONS
- '
- ' CH byte = CURRENT HEADING DH byte = DESIRED HEADING
- ' Bit 7 = 360 degrees, North
- ' Bit 6 = 045 degrees, Northeast
- ' Bit 5 = 090 degrees, East
- ' Bit 4 = 135 degrees, Southeast
- ' Bit 3 = 180 degrees, South
- ' Bit 2 = 225 degrees, Southwest
- ' Bit 1 = 270 degrees, West
- ' Bit 0 = 315 degrees, Northwest
- '
- '
- ' CA byte = CURRENT ALTITUDE DA byte = DESIRED ALTITUDE
- ' Bit 7 = 7,000 feet AGL
- ' Bit 6 = 6,000 Feet AGL
- ' Bit 5 = 5,000 Feet AGL
- ' Bit 4 = 4,000 Feet AGL
- ' Bit 3 = 3,000 Feet AGL
- ' Bit 2 = 2,000 Feet AGL
- ' Bit 1 = 1,000 Feet AGL
- ' Bit 0 = 0 Feet AGL
- '
- ' LR byte = LEFT or RIGHT TURN, SPEED, ACTIVITY
- ' Bit 7 = Left
- ' Bit 6 = Right
- ' Bit 5 = Unused
- ' Bit 4 = Speed 090 knots UH-1H
- ' Bit 3 = Speed 120 knots T-37
- ' Bit 2 = Speed 180 knots F-15E
- ' Bit 1 = OFF(0)=Awaiting takeoff ON(1)=Inflight on radar screen
- ' Bit 0 = OFF(0)=Inactive ON(1)=Active on traffic list
- '
- ' VOR byte = VOR1 or VOR2 STATUS
- ' Bit 5-7 = Unused
- ' Bit 4 = Right turn at VOR
- ' Bit 3 = Left turn at VOR
- ' Bit 2 = VOR2
- ' Bit 1 = VOR1
- ' Bit 0 = ON(1)=HOLD ACTIVATED
- '
- ' SP byte = SPEED COUNTER
- ' Bit 5-7 = Unused
- ' Bit 4 = 090 knots UH-1H
- ' Bit 3 = 120 knots T-37
- ' Bit 2 = 180 knots F-15E
- ' Bit 1 = Reset Speed Counter
- ' Bit 0 = Unused
- '
- ' MC byte = MOVEMENT NUMBER COUNTER
- ' Bits 6-7 Unused
- ' Bit 5 = Movement #5
- ' Bit 4 = Movement #4
- ' Bit 3 = Movement #3
- ' Bit 2 = Movement #2
- ' Bit 1 = Movement #1
- ' BIT 0 = Unused
- '
- ' *** END BYTE DEFINITIONS
- ' *******
- ' ASSEMBLER SUBROUTINE WRITTEN BY JERRY BETHEL (DELPHI: BETHEL)-Public Domain
- '
- ' *** ASSEMBLER CHECK WHICH BIT IS SET IN BYTE ***
- '
- ' move.w 4(sp),d1
- ' moveq.l #7,d0
- ' loop: btst d0,d1
- ' dbne d0,loop
- ' rts
- ' *******
- ' ASSEMBLER SUBROUTINE WRITTEN BY JERRY BETHEL (DELPHI: BETHEL)-Public Domain
- '
- ' *** ASSEMBLER MOVE RASTER #1 IN MODE 3 ***
- '
- ' move.l 4(sp),a0 !move source and destination addresses to stack
- ' move.l 8(sp),a1
- ' addq.l #6,a0 !ignore 3 word PUT$ header
- ' move.w #799,d0 !use d0 as counter
- ' loop1:
- ' move.l (a0)+,(a1)+ !Move long words from source to destination
- ' move.l (a0)+,(a1)+ !ten at a time
- ' move.l (a0)+,(a1)+ !for total 8,000 words or 32,000 bytes
- ' move.l (a0)+,(a1)+
- ' move.l (a0)+,(a1)+
- ' move.l (a0)+,(a1)+
- ' move.l (a0)+,(a1)+
- ' move.l (a0)+,(a1)+
- ' move.l (a0)+,(a1)+
- ' move.l (a0)+,(a1)+
- ' dbf d0,loop1 !decrement counter and brach to loop until d0=FALSE
- ' rts
- '
- ' *******
- ' ASSEMBLER SUBROUTINE WRITTEN BY JERRY BETHEL (DELPHI: BETHEL)-Public Domain
- '
- ' *** ASSEMBLER MOVE RASTER #2 IN MODE 6 ***
- ' move.l 4(sp),a0
- ' move.l 8(sp),a1
- ' addq.l #6,a0
- ' move.w #7999,d0
- ' loop1:
- ' move.l (a0)+,d1
- ' eor.l d1,(a1)+
- ' dbf d0,loop1
- ' rts
- '
- ' *******
- ' ASSEMBLER SUBROUTINE WRITTEN BY JERRY BETHEL (DELPHI: BETHEL)-Public Domain
- '
- ' *** ASSEMBLER TEXT COMMAND, SLIGHTLY FASTER ***
- '
- ' bra main
- ' contrl: ds.l 1
- ' intin: ds.l 1
- ' ptsin: ds.l 1
- ' intout: ds.l 1
- ' ptsout: ds.l 1
- ' main:
- ' move.l contrl,a0
- ' move.w #8,0(a0) ;opcode
- ' move.w #1,2(a0) ;points in ptsin
- ' move.w #2,12(a0) ;workstation handle
- ' move.l 4(sp),a1
- ' move.w 4(a1),d1 ;# of characters
- ' move.w d1,6(a0)
- ' move.l ptsin,a0
- ' move.l 8(sp),(a0) ;x and y coordinates
- ' move.l (a1),a1 ;text pointer
- ' clr.w d0
- ' move.l intin,a0
- ' loop:
- ' move.b (a1+),d0
- ' move.w d0,(a0)+
- ' dbf d1,loop
- ' move.w #$73,d0
- ' lea contrl,a0
- ' move.l a0,d1
- ' trap #2
- ' rts
- '
- ' *******
- ' ASSEMBLER SUBROUTINE USED WITH PERMISSION BY KINETIC MICROSYSTEMS
- ' FROM THE ANIMATIC-ANIMATION SYSTEM PROGRAM
- '
- ' *** ASSEMBLER PUT RASTER (STORM SEQUENCE) in MODE ***
- ' ; put_image(screen_base, image_buffer, x, y, width, height)
- ' ; int *screen_base, *image_buffer, x, y, width, height, mode
- ' ; Draws the retangular region stored in the image buffer to the
- ' ; screen at the specified co-ordinates. t
- ' put_image:
- ' movem.l D0-D7/A0-A2, -(A7) ; Save registers on the stack
- ' ; This subtracts 44 bytes from A7
- ' ; (the stack grows down)
- ' ; Get the parameters passed to us.
- ' ; These are pushed on the stack in reverse
- ' ; order of their appearance in the function call
- ' ; The first longword on the stack is the return address
- ' move.l 48(A7), A0 ; Get screen base in A0
- ' move.l 52(A7), A1 ; Get image buffer in A1
- ' move.w 56(A7), D5 ; Get x co-ord
- ' move.w 58(A7), D6 ; Get y co-ord
- ' move.w 60(A7), D7 ; Get width
- ' move.w 62(A7), D4 ; Get height
- ' ; The "mode" parameter is at 64(A7)
- ' muls #160, D6 ; 160 bytes of screen memory per scanline
- ' add.l D6, A0 ; Add y offset to screen RAM pointer
- ' and.w #$FFF0, D5 ; Round x co-ord to nearest 16
- ' asr.w #1, D5 ; 1 byte per 2 pixels
- ' add.l D5, A0 ; Add x offset to screen RAM pointer
- ' move.l A0, A2 ; Save a copy of pointer for later use
- ' move.w 56(A7), D5 ; Get x co-ord again
- ' move.w D5, D6 ; And again
- ' and.w #$FFF0, D5 ; Round x down to nearest 16
- ' sub.w D5, D6 ; D6 = D6 - D5
- ' moveq #16, D5
- ' sub.w D6, D5 ; D5 = 16 - D5 (This is our shift count)
- ' ; We calculate three masks to save time later
- ' ; These are stored on the stack
- ' move.l #$0000FFFF, D0 ; Mask 1
- ' lsl.l D5, D0 ; Shift mask 1
- ' not.l D0 ; Take logical complement
- ' move.l D0, -(A7) ; Store mask 1 on the stack
- ' move.w D7, D1 ; Get a copy of width in D1
- ' subq.w #1, D1 ; width - 1
- ' and.w #$FFF0, D1 ; Round D1 down to nearest 16
- ' add.w #16, D1 ; Add 16 (we have effectively rounded
- ' ; up to the nearest 16)
- ' move.w D7, D2 ; Get a copy of width in D2
- ' sub.w D2, D1 ; D1 = D1 - D2
- ' ; Mask 2 is used to mask off bits past
- ' ; the end of the rectangle we're affecting
- ' move.l #$0000FFFF, D0 ; Mask 2
- ' lsl.w D1, D0 ; Shift the mask
- ' move.w D0, -(A7) ; Put mask 2 on the stack
- ' ; Mask 3
- ' lsl.l D5, D0 ; Shift mask 2
- ' not.l D0 ; Take the logical complement
- ' move.l D0, -(A7) ; Put mask 3 on the stack
- ' ; NOTE:
- ' ; Pushing the masks on the stack has
- ' ; decremented the stack pointer by 10.
- ' subq.w #1, D4 ; Subtract one from height; our loop
- ' ; decrement instruction dbf goes to
- ' ; to -1, not zero.
- ' next_y:
- ' move.w 70(A7), D6 ; Get a copy of width
- ' subq.w #1, D6 ; A width of 16 should give 1 word, not 2
- ' asr.w #4, D6 ; D6 = D6 / 16
- ' cmp.w #0, D6 ; D6 = 0 ?
- ' beq trailer ; yes; only one word -- it's the trailer
- ' ; no; do all words up to the trailer
- ' subq.w #1, D6 ; dbf decrements to -1, not zero
- ' next_x: ; Get the next 16 pixels into the high
- ' ; words of the registers. We do this
- ' ; by moving the data into the low words
- ' ; and then swapping the register halves.
- ' moveq #0, D0 ; Clear D0
- ' moveq #0, D1 ; Clear D1
- ' moveq #0, D2 ; Clear D2
- ' moveq #0, D3 ; Clear D3
- ' move.w (A1)+, D0 ; Get 1st bit plane into low word of D0
- ' move.w (A1)+, D1 ; Get 2nd bit plane into low word of D1
- ' move.w (A1)+, D2 ; Get 3rd bit plane into low word of D2
- ' move.w (A1)+, D3 ; Get 4th bit plane into low word of D3
- ' lsl.l D5, D0 ; Shift D0
- ' lsl.l D5, D1 ; Shift D1
- ' lsl.l D5, D2 ; Shift D2
- ' lsl.l D5, D3 ; Shift D3
- ' moveq #0, D7 ; Clear D7
- ' move.w 74(A7), D7 ; Get "mode" parameter
- ' cmp.w #0, D7 ; mode = 0 ?
- ' beq opaque ; yes; this is an opaque copy
- ' ; no; this is a transparent copy
- ' move.l D0, D7 ; or all 4 planes together:
- ' or.l D1, D7 ;
- ' or.l D2, D7 ;
- ' or.l D3, D7 ;
- ' not.l D7 ; Take logical complement of D7
- ' opaque:
- ' or.l 6(A7), D7 ; or with mask 1
- ' addq.l #8, A0 ; Point to low word of bit plane 1
- ' and.w D7, (A0) ; and plane 1 of screen RAM with mask
- ' or.w D0, (A0)+ ; or plane 1 of data with screen RAM
- ' and.w D7, (A0) ; and plane 2 of screen RAM with mask
- ' or.w D1, (A0)+ ; or plane 2 of data with screen RAM
- ' and.w D7, (A0) ; and plane 3 of screen RAM with mask
- ' or.w D2, (A0)+ ; or plane 3 of data with screen RAM
- ' and.w D7, (A0) ; and plane 4 of screen RAM with mask
- ' or.w D3, (A0)+ ; or plane 4 of data with screen RAM
- ' sub.l #16, A0 ; Point to high word of bit plane 1
- ' swap D0 ; Swap register halves to get high word
- ' swap D1 ; Swap register halves to get high word
- ' swap D2 ; Swap register halves to get high word
- ' swap D3 ; Swap register halves to get high word
- ' swap D7 ; Swap register halves of mask too
- ' and.w D7, (A0) ; and plane 1 of screen RAM with mask
- ' or.w D0, (A0)+ ; or plane 1 of data with screen RAM
- ' and.w D7, (A0) ; and plane 2 of screen RAM with mask
- ' or.w D1, (A0)+ ; or plane 2 of data with screen RAM
- ' and.w D7, (A0) ; and plane 3 of screen RAM with mask
- ' or.w D2, (A0)+ ; or plane 3 of data with screen RAM
- ' and.w D7, (A0) ; and plane 4 of screen RAM with mask
- ' or.w D3, (A0)+ ; or plane 4 of data with screen RAM
- ' dbf D6, next_x ; Do the next 16 pixels
- ' trailer: ; The last word is special.
- ' ; We need to mask off bits that fill out
- ' ; the last word, but are past the end
- ' ; of the rectangle we are affecting.
- ' moveq #0, D0 ; Clear D0
- ' moveq #0, D1 ; Clear D1
- ' moveq #0, D2 ; Clear D2
- ' moveq #0, D3 ; Clear D3
- ' move.w (A1)+, D0 ; Get next word of image data (plane 1)
- ' move.w (A1)+, D1 ; Get next word of image data (plane 2)
- ' move.w (A1)+, D2 ; Get next word of image data (plane 3)
- ' move.w (A1)+, D3 ; Get next word of image data (plane 4)
- ' move.w 4(A7), D7 ; Get a copy of mask 2
- ' and.w D7, D0 ; and mask 2 with D0
- ' and.w D7, D1 ; and mask 2 with D1
- ' and.w D7, D2 ; and mask 2 with D2
- ' and.w D7, D3 ; and mask 2 with D3
- ' lsl.l D5, D0 ; Shift plane 1
- ' lsl.l D5, D1 ; Shift plane 2
- ' lsl.l D5, D2 ; Shift plane 3
- ' lsl.l D5, D3 ; Shift plane 4
- ' moveq #0, D7 ; Clear D7
- ' move.w 74(A7), D7 ; Get "mode" parameter
- ' cmp.w #0, D7 ; mode = 0 ?
- ' beq opaque2 ; yes; this is an opaque copy
- ' ; no; this is a transparent copy
- ' move.l D0, D7 ; or all planes together:
- ' or.l D1, D7 ;
- ' or.l D2, D7 ;
- ' or.l D3, D7 ;
- ' not.l D7 ; Take logical complement of D7
- ' opaque2:
- ' or.l (A7), D7 ; or with mask 3
- ' addq.l #8, A0 ; Point to low word of bit plane 1
- ' and.w D7, (A0) ; and plane 1 of screen RAM with mask
- ' or.w D0, (A0)+ ; or plane 1 of data with screen RAM
- ' and.w D7, (A0) ; and plane 2 of screen RAM with mask
- ' or.w D1, (A0)+ ; or plane 2 of data with screen RAM
- ' and.w D7, (A0) ; and plane 3 of screen RAM with mask
- ' or.w D2, (A0)+ ; or plane 3 of data with screen RAM
- ' and.w D7, (A0) ; and plane 4 of screen RAM with mask
- ' or.w D3, (A0)+ ; or plane 4 of data with screen RAM
- ' sub.l #16, A0 ; Point to high word of bit plane 1
- ' swap D0 ; Swap register halves to get high word
- ' swap D1 ; Swap register halves to get high word
- ' swap D2 ; Swap register halves to get high word
- ' swap D3 ; Swap register halves to get high word
- ' swap D7 ; Swap register halves of mask too
- ' and.w D7, (A0) ; and plane 1 of screen RAM with mask
- ' or.w D0, (A0)+ ; or plane 1 of data with screen RAM
- ' and.w D7, (A0) ; and plane 2 of screen RAM with mask
- ' or.w D1, (A0)+ ; or plane 2 of data with screen RAM
- ' and.w D7, (A0) ; and plane 3 of screen RAM with mask
- ' or.w D2, (A0)+ ; or plane 3 of data with screen RAM
- ' and.w D7, (A0) ; and plane 4 of screen RAM with mask
- ' or.w D3, (A0)+ ; or plane 4 of data with screen RAM
- ' add.l #160, A2 ; Point to start of image on next line
- ' move.l A2, A0
- ' dbf D4, next_y ; Do the next scan line
- ' add.l #10, A7 ; Pop the three masks off the stack
- ' movem.l (A7)+, D0-D7/A0-A2 ; Restore registers from the stack
- ' rts ; Return
- '
- ' *** END ASSEMBLY SUBROUTINES
- RETURN
- '
- ' *** START TITLE SONG PLAYING IN INTERRUPT WITH XBIOS CALL ***
- '
- PROCEDURE play_title_song
- i%=2
- RESTORE title_song_data
- GOSUB make_song_string
- RESTORE measure_1
- GOSUB make_song_string
- RESTORE measure_3
- GOSUB make_song_string
- RESTORE measure_6
- GOSUB make_song_string
- RESTORE measure_3
- GOSUB make_song_string
- RESTORE measure_7
- GOSUB make_song_string
- RESTORE measure_1
- GOSUB make_song_string
- RESTORE stop_song
- GOSUB make_song_string
- VOID XBIOS(32,L:title_song_adr%)
- RETURN
- '
- ' *** MAKE TITLE SONG 'DOSOUND' STRING, "Beacon Beats by Kevin Mason" ***
- '
- PROCEDURE make_song_string
- DEC i%
- REPEAT
- READ a%
- MID$(title_song$,i%,1)=CHR$(a%)
- INC i%
- UNTIL a%=-1
- '
- title_song_data:
- ' ! Register 6 and 7 = Enable Voices A-B, Noise Off
- ' ! Register 11 = Envelope Fine Period, followed by value
- ' ! Register 12 = Envelope Coarse Period, followed by value
- ' ! Register 13 = Envelope Shape, followed by value
- DATA 6,0
- DATA 7,&x11111100
- DATA 11,120
- DATA 12,80
- DATA 13,9
- ' ! Volume and Envelope Enable Voices A-B
- DATA 8,18
- DATA 9,0
- DATA 10,0
- DATA -1
- measure_1:
- ' ! Register 0 = Fine Tune Voice A, followed by value
- ' ! Register 1 = Coarse Tune Voice A, followed by value
- ' ! Register 255 = Delay, followed by value 1 = 1/50 second (15 = 1/8th note)
- DATA 0,131,1,7,255,14
- DATA 8,0,255,1,8,18,13,9
- DATA 0,131,1,7,255,42
- DATA 8,0,255,1,8,18,13,9
- DATA 0,131,1,7,255,56
- DATA 8,0,255,1,8,18,13,9
- ' !Measure 2
- DATA 0,131,1,7,255,14
- DATA 8,0,255,1,8,18,13,9
- DATA 0,131,1,7,255,42
- DATA 8,0,255,1,8,18,13,9
- DATA 0,131,1,7,255,56
- DATA 8,0,255,1,8,18,13,9,9,13
- DATA -1
- measure_3:
- ' ! Register 2 = Fine Tune Voice B, followed by value
- ' ! Register 3 = Coarse Tune Voice B, followed by value
- DATA 0,131,1,7,2,221,3,1,255,14
- DATA 8,0,255,1,8,18,13,9
- DATA 0,131,1,7,2,221,3,1,255,42
- DATA 8,0,255,1,8,18,13,9
- DATA 0,131,1,7,2,221,3,1,255,14
- DATA 9,0,255,1,9,13
- DATA 0,131,1,7,2,221,3,1,255,14
- DATA 9,0,255,1,9,13
- DATA 0,131,1,7,2,169,3,1,255,6
- DATA 9,0,255,1,9,13
- DATA 0,131,1,7,2,221,3,1,255,6
- DATA 9,0,255,1,9,13
- DATA 0,131,1,7,2,169,3,1,255,16
- DATA 8,0,9,0,255,1,8,18,13,9,9,13
- ' !Measure 4
- DATA 0,131,1,7,2,123,3,1,255,14
- DATA 8,0,255,1,8,18,13,9
- DATA 0,131,1,7,2,123,3,1,255,42
- DATA 8,0,255,1,8,18,13,9
- DATA 0,131,1,7,2,123,3,1,255,14
- DATA 9,0,255,1,9,13
- DATA 0,131,1,7,2,123,3,1,255,14
- DATA 9,0,255,1,9,13
- DATA 0,131,1,7,2,102,3,1,255,6
- DATA 9,0,255,1,9,13
- DATA 0,131,1,7,2,123,3,1,255,6
- DATA 9,0,255,1,9,13
- DATA 0,131,1,7,2,102,3,1,255,16
- DATA 8,0,9,0,255,1,8,18,13,9,9,13
- ' !Measure 5
- DATA 0,131,1,7,2,63,3,1,255,14
- DATA 8,0,255,1,8,18,13,9
- DATA 0,131,1,7,2,63,3,1,255,42
- DATA 8,0,255,1,8,18,13,9
- DATA 0,131,1,7,2,63,3,1,255,14
- DATA 9,0,255,1,9,13
- DATA 0,131,1,7,2,221,3,1,255,14
- DATA 9,0,255,1,9,13
- DATA 0,131,1,7,2,169,3,1,255,6
- DATA 9,0,255,1,9,13
- DATA 0,131,1,7,2,221,3,1,255,6
- DATA 9,0,255,1,9,13
- DATA 0,131,1,7,2,169,3,1,255,16
- DATA 8,0,9,0,255,1,8,18,13,9,9,13
- DATA -1
- measure_6:
- DATA 0,131,1,7,2,221,3,1,255,14
- DATA 8,0,255,1,8,18,13,9
- DATA 0,131,1,7,2,221,3,1,255,42
- DATA 8,0,255,1,8,18,13,9
- DATA 0,131,1,7,2,221,3,1,255,56
- DATA 8,0,9,0,255,1,8,18,13,9,9,13
- DATA -1
- measure_7:
- DATA 0,131,1,7,2,221,3,1,255,14
- DATA 8,0,255,1,8,18,13,9
- DATA 0,131,1,7,2,221,3,1,255,42
- DATA 8,0,255,1,8,18,13,9
- DATA 0,131,1,7,2,221,3,1,255,14
- DATA 9,0,255,1,9,0
- DATA 0,131,1,7,255,14
- DATA 9,0,255,1,9,13
- DATA 0,131,1,7,2,250,3,1,255,28
- DATA 8,0,9,0,255,1,8,18,13,9,9,13
- ' !Measure 8
- DATA 0,157,1,5,2,56,3,2,255,14
- DATA 8,0,255,1,8,18,13,9
- DATA 0,157,1,5,2,56,3,2,255,28
- DATA 9,0,255,1,9,13
- DATA 0,157,1,5,2,221,3,1,255,14
- DATA 8,0,9,0,255,1,8,18,13,9,9,13
- DATA 0,157,1,5,2,221,3,1,255,28
- DATA 9,0,255,1,9,13
- DATA 0,157,1,5,2,56,3,2,255,28
- DATA 8,0,9,0,255,1,8,18,13,9,9,13
- ' !Measure 9
- DATA 0,131,1,7,2,126,3,2,255,14
- DATA 8,0,255,1,8,18,13,9
- DATA 0,131,1,7,2,126,3,2,255,28
- DATA 9,0,255,1,9,13
- DATA 0,131,1,7,2,221,3,1,255,14
- DATA 8,0,9,0,255,1,8,18,13,9,9,13
- DATA 0,131,1,7,2,221,3,1,255,28
- DATA 9,0,255,1,9,13
- DATA 0,131,1,7,2,169,3,1,255,28
- DATA 8,0,9,0,255,1,8,18,13,9,9,13
- ' !Measure 10
- DATA 0,131,1,7,2,123,3,1,255,14
- DATA 8,0,255,1,8,18,13,9
- DATA 0,131,1,7,2,123,3,1,255,42
- DATA 8,0,255,1,8,18,13,9
- DATA 0,131,1,7,2,123,3,1,255,14
- DATA 9,0,255,1,9,13
- DATA 0,131,1,7,2,221,3,1,255,14
- DATA 9,0,255,1,9,13
- DATA 0,131,1,7,2,169,3,1,255,6
- DATA 9,0,255,1,9,13
- DATA 0,131,1,7,2,221,3,1,255,6
- DATA 9,0,255,1,9,13
- DATA 0,131,1,7,2,169,3,1,255,16
- DATA 8,0,9,0,255,1,8,18,13,9,9,13
- ' !Measure 11
- DATA 0,131,1,7,2,221,3,1,255,14
- DATA 8,0,255,1,8,18,13,9
- DATA 0,131,1,7,2,221,3,1,255,42
- DATA 8,0,255,1,8,18,13,9
- DATA 0,131,1,7,2,221,3,1,255,42
- DATA 9,0,255,1
- DATA 0,131,1,7,2,221,3,1,255,14
- DATA 8,0,255,1,8,18,13,9
- DATA -1
- stop_song:
- DATA 7,255,8,0,9,0,10,0
- DATA 255,0
- DATA -1
- RETURN
- '
- ' *** LOAD AND SHOW TITLE SCREEN ***
- '
- PROCEDURE title_screen
- temp$=SPACE$(32066)
- temp_adr%=V:temp$
- BLOAD path$+"tower.pi1",temp_adr% !LOAD TITLE SCREEN
- tcolr$=MID$(temp$,3,32)
- tcolr_adr%=V:tcolr$
- VOID XBIOS(6,L:tcolr_adr%) !TITLE SCREEN COLORS
- BMOVE temp_adr%+34,titlescr_adr%,32000
- GOSUB setup_fade_in
- VOID XBIOS(5,L:titlescr_adr%,L:titlescr_adr%,-1) !SHOW TITLE SCREEN
- CLR temp$
- GOSUB white_on
- RETURN
- '
- ' *** SET UP BLINKING LIGHTS AND FADE-IN ***
- '
- PROCEDURE setup_fade_in
- white_light%=CARD{tcolr_adr%+2}
- green_light%=CARD{tcolr_adr%+4}
- red_light%=CARD{tcolr_adr%+6}
- fade%(0)=CARD{tcolr_adr%}
- fade%(1)=CARD{tcolr_adr%+18}
- fade%(2)=CARD{tcolr_adr%+14}
- fade%(3)=CARD{tcolr_adr%+20}
- fade%(4)=CARD{tcolr_adr%+22}
- fade%(5)=CARD{tcolr_adr%+24}
- fade%(6)=CARD{tcolr_adr%+26}
- fade%(7)=CARD{tcolr_adr%+28}
- fade%(8)=CARD{tcolr_adr%+16}
- fadec%(1)=9
- fadec%(2)=7
- fadec%(3)=10
- fadec%(4)=11
- fadec%(5)=12
- fadec%(6)=13
- fadec%(7)=14
- fadec%(8)=8
- FOR i%=7 TO 14
- VOID XBIOS(7,i%,fade%(0)) !TURN OFF ALL COLORS EXCEPT LIGHTS
- NEXT i%
- VOID XBIOS(7,2,fade%(0)) !GREEN TOWER BEACON OFF
- black$=STRING$(32,CHR$(0)) !SET UP BLACK SCREEN
- black_adr%=V:black$
- RETURN
- '
- ' *** RED OFF / RED ON ***
- '
- PROCEDURE red_off
- VOID XBIOS(7,3,fade%(0))
- PAUSE 20
- VOID XBIOS(7,3,red_light%) !RESET RED ON
- RETURN
- '
- ' *** GREEN BEACON ON ***
- '
- PROCEDURE green_on
- VOID XBIOS(7,2,green_light%)
- PAUSE 24
- VOID XBIOS(7,2,fade%(0))
- RETURN
- '
- ' *** WHITE-WHITE BEACON (MILITARY AIRPORT SIGNAL) ***
- '
- PROCEDURE white_on
- VOID XBIOS(7,2,white_light%)
- PAUSE 10
- VOID XBIOS(7,2,fade%(0))
- PAUSE 4
- VOID XBIOS(7,2,white_light%)
- PAUSE 10
- VOID XBIOS(7,2,fade%(0))
- RETURN
- '
- ' *** OTHER INITS ***
- '
- PROCEDURE other_inits
- bit7|=&X10000000
- ARRAYFILL mc|(),0 !MOVEMENT NUMBER COUNTER
- ARRAYFILL sp|(),0 !SPEED COUNTER
- ARRAYFILL lr|(),bit7| !LEFT, RIGHT, SPEED, ACTIVITY
- ARRAYFILL ch|(),bit7| !CURRENT HEADING - INIT North, 360 Degrees
- ARRAYFILL dh|(),bit7| !DESIRED HEADING - INIT North, 360 Degrees
- ARRAYFILL ca|(),bit7| !CURRENT ALTITUDE- INIT 7,000 feet
- ARRAYFILL da|(),bit7| !DESIRED ALTITUDE- INIT 7,000 feet
- ARRAYFILL vor|(),0 !VOR - INIT HOLD OFF
- ARRAYFILL acx%(),290 !AIRCRAFT X POSITION
- ARRAYFILL acy%(),190 !AIRCRAFT Y POSITION
- ARRAYFILL x%(),0 !TEMPORARY ARRAYS FOR NEARMISS/COLLISION, X POS
- ARRAYFILL y%(),0 !Y POS
- ARRAYFILL a|(),0 !ALTITUDE
- ARRAYFILL id|(),0 !AIRCRAFT ID#
- temp$=" "
- FOR i%=1 TO 12
- trafname$(i%)=temp$ !TRAFFIC LIST
- arvdest$(i%)=temp$
- vor$(i%)=" "
- j%=ADD(16,MUL(i%,15))
- trafnamey%(i%)=SUB(j%,9)
- arvdesty%(i%)=SUB(j%,3)
- NEXT i%
- CLR temp$
- entryx%(1)=85 !ENTRY FIX (X) DENVER (DNV)
- entryy%(1)=13 !ENTRY FIX (Y) DENVER
- entryx%(2)=145 ! OKLAHOMA CITY (OKC)
- entryy%(2)=13
- entryx%(3)=225 ! ADA (ADA)
- entryy%(3)=93
- entryx%(4)=145 ! DALLAS-FORT WORTH (DFW)
- entryy%(4)=183
- entryx%(5)=85 ! LUBBOCK (LUB)
- entryy%(5)=183
- entryx%(6)=15 ! AMARILLO (AMR)
- entryy%(6)=53
- entryx%(7)=115 ! FORT SILL (HENRY POST) AIRFIELD (FSI)
- entryy%(7)=73
- entryx%(8)=115 ! LAWTON MUNICIPAL AIRPORT (LAW)
- entryy%(8)=113
- tsx%(1)=10 !INITIAL X,Y COORDINATES OF TWO THUNDERSTORM CLOUDS
- tsy%(1)=106
- tsx%(2)=38
- tsy%(2)=126
- nb%=1 !NORTH BOUNDARY
- eb%=230 !EAST BOUNDARY
- sb%=198 !SOUTH BOUNDARY
- wb%=1 !WEST BOUNDARY
- counter%=0
- heading$(7)=" N" !RADAR TARGET PRINTOUT FOR HEADING,
- heading$(6)="NE" !CORRESPOND WITH CURRENT HEADING BYTE
- heading$(5)=" E"
- heading$(4)="SE"
- heading$(3)=" S"
- heading$(2)="SW"
- heading$(1)=" W"
- heading$(0)="NW"
- point$="/"
- total_ac%=37 !ACTUALLY ONLY 36, BUT RANDOM(37)=#FROM 0 TO 36
- ac_count%=0 !KEEP COUNT OF NUMBER OF AIRCRAFT HANDLED
- ac%=1
- sac%=1 !SELECTED AIRCRAFT #1
- hand_off%=0 !# SUCCESSFUL HAND OFFS TO OTHER CONTROLLERS
- landed%=0 !# SUCCESFUL LANDINGS
- err_or%=0 !# ERRORS, WRONG EXITS, OUT OF BOUNDS, LANDED WRONG DIRECTION
- conflict%=0 !# SECONDS OF NEARMISS, SAME ALT-LESS THAN 3 MILES
- collisions%=0 !# COLLISIONS
- sm%=1 !STORM ANIMATION SEQUENCE IN TRANSPARENT MODE
- sf1%=16 !STORM CLOUD 1 FRAME NUMBER STARTS AS 16
- sf2%=16 !STORM CLOUD 2 FRAME NUMBER STARTS AS 16
- begin_storm%=RANDOM(40)+1 !STORM BEGIN ANYTIME IN FIRST 40 MINUTES
- storm_counter%=1
- change_course%=1
- start!=TRUE
- all_handled!=FALSE
- all_activated!=FALSE
- collision!=FALSE
- alert!=FALSE
- begin_storm!=FALSE
- storm!=FALSE
- storm_over!=FALSE
- GRAPHMODE 2
- DEFTEXT 11,0,0,4 !WHITE LETTERS, 6x6 FONT
- nl2#=LOG(2)
- PAUSE 200
- GOSUB green_on
- RETURN
- '
- ' *** LOAD RADAR GRID SCREEN ***
- '
- PROCEDURE load_grid_screen
- OPEN "i",#1,path$+"gridmask.scr"
- BGET #1,grid_adr%,16003
- PAUSE 1 !LET RED LIGHT BLINK
- BGET #1,grid_adr%+16003,16003
- CLOSE #1
- GOSUB white_on
- RETURN
- '
- ' *** LOAD RADAR CONTROLS OVERLAY SCREEN ***
- '
- PROCEDURE load_overlay_screen
- OPEN "i",#1,path$+"atccontl.scr"
- BGET #1,overlay_adr%,16003
- PAUSE 1 !LET RED LIGHT BLINK
- BGET #1,overlay_adr%+16003,16003
- CLOSE #1
- GOSUB green_on
- RETURN
- '
- ' *** LOAD AND ASSEMBLE PUT STRINGS and COLOR SCREEN2 PALETTE ***
- '
- PROCEDURE load_make_puts
- GOSUB red_off
- '
- pmg$=SPACE$(3100)
- BLOAD path$+"sprites.scr",VARPTR(pmg$)
- '
- exit_off$=MID$(pmg$,1,270)
- pause_off$=MID$(pmg$,271,270)
- takeoff_off$=MID$(pmg$,541,270)
- land_off$=MID$(pmg$,811,182)
- vor1_off$=MID$(pmg$,993,182)
- vor2_off$=MID$(pmg$,1175,182)
- left_off$=MID$(pmg$,1357,126)
- right_off$=MID$(pmg$,1483,126)
- head045_off$=MID$(pmg$,1609,118)
- head090_off$=MID$(pmg$,1727,118)
- head135_off$=MID$(pmg$,1845,118)
- head180_off$=MID$(pmg$,1963,118)
- head225_off$=MID$(pmg$,2081,118)
- head270_off$=MID$(pmg$,2199,118)
- head315_off$=MID$(pmg$,2317,118)
- alt1_off$=MID$(pmg$,2435,78)
- alt2_off$=MID$(pmg$,2513,78)
- alt3_off$=MID$(pmg$,2591,78)
- alt4_off$=MID$(pmg$,2669,78)
- alt5_off$=MID$(pmg$,2747,78)
- alt6_off$=MID$(pmg$,2825,78)
- '
- colrscr2$=MID$(pmg$,2903,32) !COLOR PALETTE RADAR CONSOLE
- colrscr2_adr%=VARPTR(colrscr2$)
- red%=DPEEK(colrscr2_adr%+4)
- mgray%=DPEEK(colrscr2_adr%+16)
- '
- alert_snd$=MID$(pmg$,2935,30)
- alert_snd_adr%=VARPTR(alert_snd$)
- '
- head360_off$=MID$(pmg$,2965,118)
- GOSUB white_on
- RETURN
- '
- ' *** CREATE ASSEMBLER SUBROUTINES ***
- '
- PROCEDURE setup_asm
- RESTORE which_bit_routine
- FOR i%=0 TO 6
- READ a%
- CARD{which_bit%+(i%*2)}=a%
- NEXT i%
- '
- RESTORE asmroutine1
- FOR i%=0 TO 19
- READ a%
- CARD{asmmove1_adr%+(i%*2)}=a%
- NEXT i%
- '
- RESTORE asmroutine2
- FOR i%=0 TO 11
- READ a%
- CARD{asmmove2_adr%+(i%*2)}=a%
- NEXT i%
- '
- RESTORE asm_text_routine
- FOR i%=0 TO 47
- READ a%
- CARD{asmtxt_adr%+(i%*2)}=a%
- NEXT i%
- '
- RESTORE asmroutine3
- FOR i%=0 TO 183
- READ a%
- CARD{asmput_adr%+(i%*2)}=a%
- NEXT i%
- '
- GOSUB red_off
- PAUSE 150
- GOSUB green_on
- '
- which_bit_routine:
- DATA 12847,4,28679,257,22216,65532,20085
- '
- asmroutine1:
- DATA 8303,4,8815,8,23688,12348,799,8920
- DATA 8920,8920,8920,8920,8920,8920,8920,8920
- DATA 8920,20936,65514,20085
- '
- asmroutine2:
- DATA 8303,4,8815,8,23688,12348,7999,8728
- DATA 45977,20936,65530,20085
- '
- asm_text_routine:
- DATA 24576,22,0,0,0,0,0,0
- DATA 0,0,0,0,8314,65514,12668,8
- DATA 0,12668,1,2,12668,2,12,8815
- DATA 4,12841,4,12609,6,8314,65488,8367
- DATA 8,8785,16960,8314,65472,4121,12480,20937
- DATA 65530,12348,115,16890,65452,8712,20034,20085
- '
- asmroutine3:
- DATA 18663,65504,8303,48,8815,52,14895,56
- DATA 15407,58,15919,60,14383,62,52732,160
- DATA 53702,51836,65520,57925,53701,9288,14895,56
- DATA 15365,51836,65520,40005,31248,39494,8252,0
- DATA 65535,60328,18048,12032,12807,21313,49788,65520
- DATA 53884,16,13319,37442,8252,0,65535,58216
- DATA 16128,60328,18048,12032,21316,15407,70,21318
- DATA 59462,48252,0,26368,110,21318,28672,29184
- DATA 29696,30208,12313,12825,13337,13849,60328,60329
- DATA 60330,60331,32256,15919,74,48764,0,26368
- DATA 12,11776,36481,36482,36483,18055,36527,6
- DATA 20616,53072,33112,53072,33624,53072,34136,53072
- DATA 34648,37372,0,16,18496,18497,18498,18499
- DATA 18503,53072,33112,53072,33624,53072,34136,53072
- DATA 34648,20942,65432,28672,29184,29696,30208,12313
- DATA 12825,13337,13849,15919,4,49223,49735,50247
- DATA 50759,60328,60329,60330,60331,32256,15919,74
- DATA 48764,0,26368,12,11776,36481,36482,36483
- DATA 18055,36503,20616,53072,33112,53072,33624,53072
- DATA 34136,53072,34648,37372,0,16,18496,18497
- DATA 18498,18499,18503,53072,33112,53072,33624,53072
- DATA 34136,53072,34648,54780,0,160,8266,20940
- DATA 65290,57340,0,10,19679,2047,20085,0
- RETURN
- '
- ' *** FADE_IN TITLE SCREEN, SELECT TRAFFIC VOLUME ***
- '
- PROCEDURE fade_in
- FOR i%=1 TO 8
- VOID XBIOS(7,fadec%(i%),fade%(i%))
- PAUSE 1
- NEXT i%
- BLOAD path$+"storm.scr",storm_scr_adr%
- w%=CARD{storm_scr_adr%+40} !WIDTH STORM ANIMATION FRAMES
- h%=CARD{storm_scr_adr%+42} !HEIGHT STORM ANIMATION FRAMES
- storm_base_adr%=storm_scr_adr%+64 !SKIP 32 WORD HEADER
- FOR i%=0 TO 15
- storm_adr%(i%+1)=storm_base_adr%+(i%*1152) !ADDRESS EACH STORM FRAME
- NEXT i%
- GOSUB white_on
- GOSUB make_strings
- PAUSE 150
- GOSUB green_on
- PAUSE 10
- EVERY STOP
- mess$=" | WHAT VOLUME OF TRAFFIC |DO YOU WANT TO HANDLE TODAY?| "
- button$="STUDENT|ROOKIE|MASTER"
- SHOWM
- ALERT 2,mess$,2,button$,b%
- SELECT b%
- CASE 1 !ONE NEW PLANE ADDED EVERY 2.5 min +/- 36 sec
- game_speed%=150
- game_speed_var%=72
- points_var%=1000
- bonus%=2000
- CASE 2 !ONE NEW PLANE ADDED EVERY 1.5 min +/- 24 sec
- game_speed%=90
- game_speed_var%=48
- points_var%=2000
- bonus%=4000
- CASE 3 !ONE NEW PLANE ADDED EVERY 45 sec +/- 15 sec
- game_speed%=45
- game_speed_var%=30
- points_var%=4000
- bonus%=8000
- ENDSELECT
- mess$=" | WHAT LANDING AND | TAKEOFF DIRECTION | DO YOU WANT TODAY? "
- button$="NORTH|SOUTH"
- ALERT 2,mess$,1,button$,b%
- HIDEM
- SELECT b%
- CASE 1
- land_dir%=7
- takeoff_dir%=7
- CASE 2
- land_dir%=3
- takeoff_dir%=3
- ENDSELECT
- CLR title_song$
- VOID XBIOS(6,L:black_adr%)
- '
- LONG{asmtxt_adr%+4}=CONTRL
- LONG{asmtxt_adr%+8}=INTIN
- LONG{asmtxt_adr%+12}=PTSIN
- LONG{asmtxt_adr%+16}=INTOUT
- LONG{asmtxt_adr%+20}=PTSOUT
- RETURN
- '
- ' *** MAKE STRINGS TO IDENTIFY AIRCRAFT, ARRIVALS, DESTINATIONS ***
- '
- PROCEDURE make_strings
- ac$(0)=" F999" !F=FIGHTER, JET, F-16, 180 Knots
- ac$(1)=" T249" !T=TRAINER, JET, T-37, 120 Knots
- ac$(2)=" A638" !A=ARMY, HELICOPTER, UH-1H, 090 Knots
- ac$(3)=" T155"
- ac$(4)=" F448"
- ac$(5)=" A071"
- ac$(6)=" T129"
- ac$(7)=" T774"
- ac$(8)=" A422"
- ac$(9)=" T150"
- ac$(10)=" F097"
- ac$(11)=" A814"
- ac$(12)=" T245"
- ac$(13)=" T515"
- ac$(14)=" A623"
- ac$(15)=" T997"
- ac$(16)=" F542"
- ac$(17)=" A151"
- ac$(18)=" T400"
- ac$(19)=" T842"
- ac$(20)=" A740"
- ac$(21)=" T484"
- ac$(22)=" F965"
- ac$(23)=" A357"
- ac$(24)=" T596"
- ac$(25)=" T917"
- ac$(26)=" A362"
- ac$(27)=" T763"
- ac$(28)=" F508"
- ac$(29)=" A896"
- ac$(30)=" T437"
- ac$(31)=" T674"
- ac$(32)=" A893"
- ac$(33)=" T668"
- ac$(34)=" F928"
- ac$(35)=" A458"
- ac$(36)=" T041"
- '
- RESTORE arrival_destinations
- FOR i%=0 TO 36
- READ ad$(i%)
- NEXT i%
- arrival_destinations:
- DATA OK-LU,FS-DF,AD-AM,DN-AD,LA-AM,DF-OK
- DATA AM-LA,LU-FS,LA-DF,DN-FS,DF-LA,LA-OK
- DATA FS-AM,AD-LA,AM-DF,FS-AD,OK-LA,LU-OK
- DATA FS-OK,DN-DF,OK-FS,LA-DN,AM-FS,LU-DN
- DATA LA-LU,FS-DN,DN-LU,AM-AD,LA-AD,DF-DN
- DATA LU-LA,AD-FS,OK-DF,LU-AD,FS-LU,DF-FS
- DATA AD-LU
- RETURN
- '
- ' *********************
- ' *** HOUSE KEEPING ***
- ' *********************
- '
- ' *** GET RESOLUTION, BETTER BE LOW REZ, AND GET DRIVE/PATHWAY ***
- '
- PROCEDURE get_rez_dir
- rez%=XBIOS(4)
- IF rez%>0
- mess$=" FINAL APPROACH | CONTROLLER | IN LOW REZ ONLY"
- ALERT 3,mess$,1,"DANG",b%
- QUIT
- ENDIF
- CLR rez%
- '
- path$=SPACE$(64)
- drive$=CHR$(GEMDOS(&H19)+65) !GET DRIVE NAME (A-P)
- VOID GEMDOS(&H47,L:VARPTR(path$),0)!GET PATH NAME
- i%=1
- REPEAT
- EXIT IF MID$(path$,i%,1)=CHR$(0) !STRIP PATH NAME OF SPACES
- INC i%
- UNTIL i%>64
- path$=LEFT$(path$,i%-1)
- path$=drive$+":"+path$+"\"
- mess$=" must be in the same | directory as APPROACH.GFA | and GFABASRO.PRG."
- IF NOT EXIST(path$+"tower.pi1")
- ALERT 3,"TOWER.PI1"+mess$,1,"ABORT",d%
- END
- ENDIF
- IF NOT EXIST(path$+"GRIDMASK.SCR")
- ALERT 3,"GRIDMASK.SCR"+mess$,1,"ABORT",d%
- END
- ENDIF
- IF NOT EXIST(path$+"ATCCONTL.SCR")
- ALERT 3,"ATCCONTL.SCR"+mess$,1,"ABORT",d%
- END
- ENDIF
- IF NOT EXIST(path$+"SPRITES.SCR")
- ALERT 3,"SPRITES.SCR"+mess$,1,"ABORT",d%
- END
- ENDIF
- IF NOT EXIST(path$+"STORM.SCR")
- ALERT 3,"STORM.SCR"+mess$,1,"ABORT",d%
- END
- ENDIF
- RETURN
- '
- ' *** SAVE DESKTOP COLOR PALETTE BEFORE PROGRAM STARTS ***
- '
- PROCEDURE sav_palette
- FOR i%=0 TO 15
- sav_pal%(i%)=XBIOS(7,i%,-1)
- NEXT i%
- RETURN
- '
- ' *** BLANK SCREEN ***
- '
- PROCEDURE blank_screen
- FOR i%=0 TO 15
- blank_pal%(i%)=0
- NEXT i%
- blank_pal_adr%=V:blank_pal%(0)
- VOID XBIOS(6,L:blank_pal_adr%)
- RETURN
- '
- ' *** RESTORE DESKTOP COLOR PALETTE AT PROGRAM COMPLETION ***
- '
- PROCEDURE restor_palette
- GOSUB score_card
- EVERY STOP
- FOR i%=0 TO 15
- VOID XBIOS(7,i%,sav_pal%(i%))
- NEXT i%
- SOUND 0,0,0,0
- WAVE 0,0,0,0,0
- ~MFREE(mem1%)
- ~MFREE(mem2%)
- ~MFREE(mem3%)
- ~MFREE(mem4%)
- ~MFREE(mem5%)
- ~MFREE(mem6%)
- ~MFREE(mem7%)
- ~MFREE(mem8%)
- ~MFREE(mem9%)
- ~MFREE(mem10%)
- ~MFREE(mem11%)
- RESERVE
- EDIT
- RETURN
- '
- ' *** SCORE CARD ***
- '
- PROCEDURE score_card
- VOID XBIOS(5,L:logbase%,L:physbase%,-1)
- CLS
- GRAPHMODE 1
- DEFFILL 12,2,8
- PBOX 0,0,319,199
- DEFFILL 13,2,8
- PBOX 60,15,260,185
- GRAPHMODE 2
- DEFTEXT 0,0,0,13
- TEXT 75,35," SCORE CARD"
- DEFTEXT 8,0,0,13
- points%=landed%*points_var%
- TEXT 75,55,"Landed = "+STR$(landed%)
- ADD points%,hand_off%*points_var%
- TEXT 75,75,"Handoffs = "+STR$(hand_off%)
- SUB points%,err_or%*100
- TEXT 75,95,"Errors = "+STR$(err_or%)
- SUB points%,conflict%*100
- TEXT 75,115,"Conflicts = "+STR$(conflict%)
- TEXT 75,135,"Collisions = "+STR$(collisions%)
- IF err_or%>0 OR conflict%>0 OR collisions%>0
- bonus%=0
- ENDIF
- ADD points%,bonus%
- IF collisions%>0
- points%=0
- ENDIF
- IF landed%=0 AND hand_off%=0
- points%=0
- ENDIF
- TEXT 75,155,"TOTAL POINTS = "+STR$(points%)
- DEFTEXT 0,0,0,6
- TEXT 75,175," left click to exit"
- REPEAT
- UNTIL MOUSEK=1
- CLS
- DEFTEXT 0,0,0,4
- elapsed_time%=201
- RETURN
-